package com.forsir.android.mhfinance.helper;

import java.text.SimpleDateFormat;
import java.util.Calendar;

import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;

import com.forsir.android.mhfinance.R;

public class DateInterval {
	public final static String DATE_FROM = "date_from";
	public final static String DATE_TO = "date_to";
	public final static String DATE_TYPE = "date_type";

	public final static int TYPE_CUSTOM = 0;
	public final static int TYPE_WEEK = 1;
	public final static int TYPE_MONTH = 2;
	public final static int TYPE_YEAR = 3;

	private Calendar mDateFrom = Calendar.getInstance();
	private Calendar mDateTo = Calendar.getInstance();
	private int mType = TYPE_MONTH;

	public DateInterval() {
		mDateFrom.set(mDateFrom.get(Calendar.YEAR), mDateFrom.get(Calendar.MONTH), mDateFrom.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
		mDateTo.set(mDateTo.get(Calendar.YEAR), mDateTo.get(Calendar.MONTH), mDateTo.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
		mDateFrom.set(Calendar.MILLISECOND, 0);
		mDateTo.set(Calendar.MILLISECOND, 0);
	}

	public void setDateFrom(Calendar dateFrom) {
		mDateFrom = dateFrom;
		mDateFrom.set(Calendar.MILLISECOND, 0);
	}

	public Calendar getDateFrom() {
		return mDateFrom;
	}

	public void setType(int type) {
		mType = type;
	}

	public int getType() {
		return mType;
	}

	public void setDateTo(Calendar dateTo) {
		mDateTo = dateTo;
		mDateTo.set(Calendar.MILLISECOND, 0);
	}

	public Calendar getDateTo() {
		final Calendar dateTo = (Calendar) mDateFrom.clone();
		switch (mType) {
			case TYPE_CUSTOM:
				return mDateTo;
			case TYPE_WEEK:
				dateTo.add(Calendar.WEEK_OF_YEAR, 1);
				break;
			case TYPE_MONTH:
				dateTo.add(Calendar.MONTH, 1);
				break;
			case TYPE_YEAR:
				dateTo.add(Calendar.YEAR, 1);
				break;
			default:
				break;
		}

		return dateTo;
	}

	public void findFirstDate() {
		switch (mType) {
			case TYPE_CUSTOM:
				break;
			case TYPE_WEEK:
				mDateFrom.set(Calendar.DAY_OF_WEEK, 1);
				break;
			case TYPE_MONTH:
				mDateFrom.set(Calendar.DAY_OF_MONTH, 1);
				break;
			case TYPE_YEAR:
				mDateFrom.set(Calendar.MONTH, Calendar.JANUARY);
				mDateFrom.set(Calendar.DAY_OF_MONTH, 1);
				break;
		}
		mDateFrom.set(Calendar.HOUR_OF_DAY, 0);
		mDateFrom.set(Calendar.MINUTE, 0);
		mDateFrom.set(Calendar.SECOND, 0);
		mDateFrom.set(Calendar.MILLISECOND, 0);
	}

	public void moveToBoundaries(Calendar fromDate, Calendar toDate) {
		while (getDateTo().before(fromDate)) {
			moveToNext();
		}
		while (mDateFrom.after(toDate)) {
			moveToPrevious();
		}
	}

	public void moveToNext() {
		switch (mType) {
			case TYPE_CUSTOM:
				long sub = mDateTo.getTimeInMillis() - mDateFrom.getTimeInMillis();
				sub = sub / 86400000l; // (1000 * 60 * 60 * 24);
				final int day = (int) sub;
				mDateFrom.add(Calendar.DAY_OF_YEAR, day);
				mDateTo.add(Calendar.DAY_OF_YEAR, day);
				break;
			case TYPE_WEEK:
				mDateFrom.add(Calendar.WEEK_OF_YEAR, 1);
				break;
			case TYPE_MONTH:
				mDateFrom.add(Calendar.MONTH, 1);
				break;
			case TYPE_YEAR:
				mDateFrom.add(Calendar.YEAR, 1);
				break;
		}
	}

	public void moveToPrevious() {
		switch (mType) {
			case TYPE_CUSTOM:
				long sub = mDateTo.getTimeInMillis() - mDateFrom.getTimeInMillis();
				sub = sub / 86400000l; // (1000 * 60 * 60 * 24);
				final int day = -(int) sub;
				mDateFrom.add(Calendar.DAY_OF_YEAR, day);
				mDateTo.add(Calendar.DAY_OF_YEAR, day);
				break;
			case TYPE_WEEK:
				mDateFrom.add(Calendar.WEEK_OF_YEAR, -1);
				break;
			case TYPE_MONTH:
				mDateFrom.add(Calendar.MONTH, -1);
				break;
			case TYPE_YEAR:
				mDateFrom.add(Calendar.YEAR, -1);
				break;
		}
	}

	public CharSequence getDateString(Resources resource) {
		final SimpleDateFormat format = new SimpleDateFormat(resource.getString(R.string.format_date));

		switch (mType) {
			case TYPE_CUSTOM:
				return format.format(mDateFrom.getTime());

			case TYPE_WEEK:
				final Calendar dateTo = getDateTo();
				final String dateFromString = format.format(mDateFrom.getTime());
				final String dateToString = format.format(dateTo.getTime());

				// if (mDateFrom.get(Calendar.YEAR) == dateTo.get(Calendar.YEAR)) {
				// if (mDateFrom.get(Calendar.MONTH) == dateTo.get(Calendar.MONTH)) {
				// dateFromString = String.valueOf(mDateFrom.get(Calendar.DAY_OF_MONTH));
				// } else {
				// // year must be 4 chars
				// dateFromString = (String) dateFromString.subSequence(0, dateFromString.length() - 4);
				// }
				// }

				return dateFromString + " - " + dateToString;

			case TYPE_MONTH:
				return resource.getTextArray(R.array.months)[mDateFrom.get(Calendar.MONTH)] + " " + mDateFrom.get(Calendar.YEAR);

			case TYPE_YEAR:
				return String.valueOf(mDateFrom.get(Calendar.YEAR));
		}
		return "";
	}

	public CharSequence getDateToString(Resources resource) {
		if (mType != TYPE_CUSTOM) {
			return "";
		}

		final SimpleDateFormat format = new SimpleDateFormat(resource.getString(R.string.format_date));

		return format.format(mDateTo.getTime());
	}

	public DateInterval fillFromBundle(Bundle bundle) {
		if (bundle == null) {
			return this;
		}

		mDateFrom.setTimeInMillis(bundle.getLong(DATE_FROM));
		mDateFrom.set(Calendar.SECOND, 0);
		mDateFrom.set(Calendar.MILLISECOND, 0);
		mDateTo.setTimeInMillis(bundle.getLong(DATE_TO));
		mDateTo.set(Calendar.SECOND, 0);
		mDateTo.set(Calendar.MILLISECOND, 0);
		mType = bundle.getInt(DATE_TYPE);

		return this;
	}

	public Bundle fillBundle(Bundle bundle) {
		if (bundle == null) {
			return null;
		}

		bundle.putLong(DATE_FROM, mDateFrom.getTimeInMillis());
		bundle.putLong(DATE_TO, mDateTo.getTimeInMillis());
		bundle.putInt(DATE_TYPE, mType);

		return bundle;
	}

	public Intent fillIntent(Intent intent) {
		if (intent == null) {
			return null;
		}

		intent.putExtra(DATE_FROM, mDateFrom.getTimeInMillis());
		intent.putExtra(DATE_TO, mDateTo.getTimeInMillis());
		intent.putExtra(DATE_TYPE, mType);

		return intent;
	}

	public boolean isEmpty() {
		return mDateFrom.getTimeInMillis() == 0l;
	}

}
